Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nsenter: set {uid,gid} explicitly around namespace creation #975

Closed
wants to merge 1 commit into from
Closed

nsenter: set {uid,gid} explicitly around namespace creation #975

wants to merge 1 commit into from

Conversation

cyphar
Copy link
Member

@cyphar cyphar commented Aug 8, 2016

In general, it is a bad idea to be unmapped inside a user namespace at
any point (especially when euid=[kuid 0]) as it can lead to security
vulnerabilities. Also, in certain SELinux setups you must also be mapped
in your user namespace when unsharing other namespaces.

Deal with all of this by parsing the {uid,gid}maps and then setresuid(2)
to the right user before and after the critical unshare(CLONE_NEWUSER)
(as well as dealing with setns(2) by changing user to the owner of the
namespace file we're joining).

Fixes: CVE-2015-8709
Reported-by: Andrey Vagin avagin@virtuozzo.com
Reported-by: Mrunal Patel mpatel@redhat.com
Signed-off-by: Aleksa Sarai asarai@suse.de

Fixes #959.

Note: This is based on #950 and #977.

@cyphar
Copy link
Member Author

cyphar commented Aug 31, 2016

NOTE: map_field is slightly broken at the moment (it currently only can parse the first line of the map data). I'll fix this later, but right now don't merge this. This isn't a problem for us and can be fixed at a later date. I've added a comment to note this.


/* Cache the user namespace entry. */
if (ns->ns == CLONE_NEWUSER || !strcmp(namespace, "user"))
userns = ns;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When ns->ns == CLONE_NEWUSER, the !strcmp(namespace, "user") must be true.
So, this code maybe simplify as following:

if (ns->ns == CLONE_NEWUSER)
        userns = ns;

Copy link
Member Author

@cyphar cyphar Oct 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC I wrote it like this to avoid issues where CLONE_NEWUSER is not defined by glibc (so nsflags would return 0). Though I might have fixed that in the meantime, since CLONE_NEWUSER is required by a bunch of other things. I'll take a look later.

@cyphar
Copy link
Member Author

cyphar commented Oct 26, 2016

This has been rebased. @avagin can you double-check that this fix still is fine, since I had to un-split the unshare(CLONE_NEWUSER) I'm worried that we haven't actually fixed the issue.

/cc @opencontainers/runtime-spec-maintainers

@crosbymichael
Copy link
Member

crosbymichael commented Oct 31, 2016

LGTM

Approved with PullApprove

@mrunalp
Copy link
Contributor

mrunalp commented Oct 31, 2016

unshare fails with EPERM on RHEL 7.

if (setresgid(config.hostgid, config.hostgid, config.hostgid) < 0)
bail("failed to set gid to host");
if (setresuid(config.hostuid, config.hostuid, config.hostuid) < 0)
bail("failed to set uid to host");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrunalp I guess this is what's causing the failure. The problem is that this is the fix for the security issue (a racing ptrace can cause root privilege escalation inside a container). I'm starting to think that the issues here are on the SELinux side and not on the runC side...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cyphar I'll look closer but it looked like the split of unshare or NEWUSER and the other cloneflags.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recently, I read an email on a kernel mailing list about "safely creating container processes" and the process for doing it safely is actually quite a bit more complicated than what we're doing now. Essentially the method requires creating a "sacrifical" user namespace before we create all of the actual container namespaces (you unshare(CLONE_NEWUSER) twice). The problem is that because of SELinux we simply can't implement that -- which IMO is a serious problem.

I'll see if I can find the email. My point is that I feel like the issues are on the kernel side of things, because I'm trying to make this process safer and SELinux is having problems with it. If worse comes to worst we can have SELinux-specific code here that changes how we create containers -- it won't be pretty but at least container creation will be safer without breaking SELinux support.

In general, it is a bad idea to be unmapped inside a user namespace at
any point (especially when euid=[kuid 0]) as it can lead to security
vulnerabilities. Also, in certain SELinux setups you must also be mapped
in your user namespace when unsharing other namespaces.

Deal with all of this by parsing the {uid,gid}maps and then setresuid(2)
to the right user before and after the critical unshare(CLONE_NEWUSER)
(as well as dealing with setns(2) by changing user to the owner of the
namespace file we're joining).

Fixes: CVE-2015-8709
Reported-by: Andrey Vagin <avagin@virtuozzo.com>
Reported-by: Mrunal Patel <mpatel@redhat.com>
Signed-off-by: Aleksa Sarai <asarai@suse.de>
@cyphar
Copy link
Member Author

cyphar commented Feb 28, 2017

Rebased.

@mrunalp If we get this merged then the split code for #959 will look much better in my opinion (it would be a few lines apart as opposed to being in separate processes).

@dqminh
Copy link
Contributor

dqminh commented Aug 1, 2017

@cyphar can you rebase this change if still relevant ?

@cyphar
Copy link
Member Author

cyphar commented Aug 18, 2017

@dqminh Yes, and I'm going to carry this and #959 to see if we can finally resolve these issues in a more sane way.

@cyphar
Copy link
Member Author

cyphar commented Aug 18, 2017

#1562 is my attempt to carry this and #959 together.

@crosbymichael
Copy link
Member

Closing since #1562 takes care of this. Just cleaning up the milestone some.

@cyphar cyphar deleted the nsenter-setuid-cve20158709 branch October 10, 2017 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants